use crate::config_util;
use crate::cmd_util;
use crate::list_util;
use crate::path_util;
use crate::env_util::get_env_is_dev;

fn run_with_target_cmd(
  other_arg: &Vec<String>,
  target_cmd: &str,
  work_directory: &str
) {
  let (position_arg_cmd, exclude_index_list) = cmd_util::build_cmd_str::use_position_arg(&other_arg, target_cmd);
  let remain_arg_list = list_util::exclude_item_by_index_list(other_arg.to_owned(), exclude_index_list);
  let remain_arg_txt = remain_arg_list.join(" ");
  let result_cmd = cmd_util::build_cmd_str::use_remain_arg(remain_arg_txt.as_str(), position_arg_cmd.as_str());
  if get_env_is_dev() {
    println!("run cmd:[{}]; work directory: [{}]", result_cmd, work_directory);
    return;
  }
  cmd_util::build_cmd::run_cmd(result_cmd.as_str(), work_directory);
}

pub fn plain_run(raw_arg_list: &Vec<String>, cmd_id: &str) {  
  let (target_cmd, work_directory) = config_util::get_cmd_and_work_directory(cmd_id);
  if target_cmd.is_empty() {
    let result_cmd = Vec::from(&raw_arg_list[1..]).join(" ");
    cmd_util::build_cmd::run_cmd(result_cmd.as_str(), work_directory.as_str());
    return;
  }
  let other_arg = raw_arg_list[2..].to_vec();
  run_with_target_cmd(&other_arg, target_cmd.as_str(), work_directory.as_str());
}

pub fn run_with_sequence_arg(raw_arg_list: &Vec<String>) {
  if raw_arg_list.len() >= 4 {
    let cmd_id = raw_arg_list.iter().nth(2).unwrap();
    let other_arg_list = (&raw_arg_list[3..]).to_vec();
    let mut sequence_arg_list = Vec::<String>::new();
    other_arg_list.iter().for_each(|arg_one| {
        let target_arg = format!("{} {}", cmd_id, arg_one);
        sequence_arg_list.push(target_arg);
    });
    run_in_sequence(&sequence_arg_list);
    return;
  }
  panic!("raw arg list length should not < 4 while arg is [{:?}]", raw_arg_list);
}

pub fn run_in_sequence(raw_arg_list: &Vec<String>) {
  let path_list = path_util::get_config_toml_path_name_list();
  let config_iter = path_list.iter().map(|config_file_path| {
      return config_util::read_from_toml(config_file_path.as_str());
  });
  let config_list: Vec<config_util::full_config::FullConfig> = config_iter.collect();
  raw_arg_list.iter().for_each(|cmd_one| {
    run_one_in_sequence(cmd_one.as_str(), &config_list);
  });
}

fn split_cmd_str(cmd: &str) -> Vec<String> {
  let mut result_list = Vec::<String>::new();
  cmd.split(" ").for_each(|one| {
    if !one.is_empty() {
      result_list.push(String::from(one));
    }
  });
  return result_list;
}

fn run_one_in_sequence(cmd: &str, config_list: &Vec<config_util::full_config::FullConfig>) {
  let arg_list = split_cmd_str(cmd);
  if arg_list.is_empty() {
    return;
  }
  let arg_cmd_id = arg_list.iter().nth(0).unwrap();
  let (target_cmd, work_directory) = config_util::get_cmd_and_work_directory_from(arg_cmd_id, config_list);
  if target_cmd.is_empty() {
    if get_env_is_dev() {
      println!("target_cmd is empty; cmd: [{}]; work directory: [{}]", cmd, work_directory);
      return;
    }
    if !cmd.is_empty() {
      cmd_util::build_cmd::run_cmd(cmd, work_directory.as_str());
      return;
    }
    panic!("wrong arg!!!");
  }  
  let other_arg = arg_list[1..].to_vec();
  run_with_target_cmd(&other_arg, target_cmd.as_str(), work_directory.as_str());
}
